#include <iostream>
#include <string>
#include <vector>
#include <array>
#include <ctime>
#include <json/json.h>
#include "MySqlApi.h"
#include "MySqlConnectPool.h"
#include "xmlgateway.h"
#include "DeviceConfig.h"

using namespace std;

// 线性转换函数
double convertToTemperature(int value)
{
    // 斜率 k
    double k = 1050.0 / 65535.0;
    // 截距 b
    double b = -200.0;
    // 计算温度
    double temperature = k * value + b;
    return temperature;
}

double convertToPressure(int value)
{
    // 斜率 k
    double k = 0.04 / 65535.0;
    // 截距 b
    double b = -0.02;
    // 计算压力
    double pressure = k * value + b;
    return pressure;
}

int main()
{
    char a = '\r';
    char b = '\n';
    cout << int(a) << "---" << int(b) << endl;
    printf("[%s:%d] 0x%X : 0x%X\n", __FILE__, __LINE__, int(a), int(b));

    // time_t now_time;
    // now_time = time(NULL);
    // cout << (unsigned long)now_time << endl;
    // printf("[%s:%d] time=%ld\n", __FILE__, __LINE__, (unsigned long)now_time);

    // XmlGateway* xml = new XmlGateway("./hld.xml");
    // xml->initXmlFile();
    //
    // xml->addChannel("1575875275",
    //                 "1","2","3","4",
    //                 "5","6","7","8");
    //
    // xml->addChannel("1575875275",
    //                 "11","22","32","44",
    //                 "5","6","7","8");



    return -1;

    // 连接DataCap软件的配置数据库
    MySqlApi* configDB = new MySqlApi("192.168.203.144", 3306, "iscuV2", "root", "0416");
    if(!configDB)
    {
        return -1;
    }

    if(!configDB->ConnDB())
    {
        printf("[%s:%d] %s\n", __FILE__, __LINE__,
               "Configuration information database connection failed");
        return -1;
    }
    else
    {
        printf("[%s:%d] %s\n", __FILE__, __LINE__,
               "Configuration information database connection successful");
    }

    CMySqlConnectPool::Instance()->InitConnection(10);

    // 查询 Nmea0183的配置

    // 查询 仿Nmea语句的配置
    {
        std::vector<std::string> vecTopicName;
        // channelsdataprotocol表
        {
            char sql[128] = "SELECT * FROM channelsdataprotocol WHERE way_uid=\'20000000\'";

            std::vector<std::map<std::string, std::string>> vecData;
            if(configDB->SelectSql(sql, vecData))
            {
                int chanCode = 9;
                for(auto vec : vecData)
                {
                    // cout << vec["topic_name"] << endl;
                    vecTopicName.push_back(vec["topic_name"]);

                    // ISCU数据库插入数据：channelsdataprotocol表
                    MySqlApi *p1 = CMySqlConnectPool::Instance()->GetConnection();
                    if (p1 != NULL)
                    {
                        char insert_sql[256];
                        sprintf(insert_sql, "INSERT INTO channelsdataprotocol(TopicName, WayUid, ChanType, ChanCode, SlaveId, DataProtocol) VALUES(\'%s\', \'%s\', %d, %d, %d, %d)",
                                vec["topic_name"].c_str(), "1575875275", 7, chanCode, 0, 5);
                        printf("[%s:%d] %s\n", __FILE__, __LINE__, insert_sql);

                        if(!p1->ExecuteSql(insert_sql))
                        {
                            printf("[%s:%d] %s\n", __FILE__, __LINE__, "MySQL INSERT failed...");
                        }
                    }
                    CMySqlConnectPool::Instance()->ReleaseConnection(p1);
                    chanCode++;
                }
            }
        }

        // sys_config.hldkeymap表
        {
            for(auto vec : vecTopicName)
            {
                int chanCode = 9;
                std::string keyValue;

                char select_sql[128];
                sprintf(select_sql, "SELECT * FROM hldkeymap WHERE topic_name=\'%s\'", vec.c_str());
                printf("[%s:%d] %s\n", __FILE__, __LINE__, select_sql);

                std::vector<std::map<std::string, std::string>> vecData;
                if(configDB->SelectSql(select_sql, vecData))
                {
                    // 语句表述{数据地址:{KeyValue，Desc, Coefficient}}
                    std::map<std::string, std::map<std::string, std::vector<std::string>>> statementIdMap;

                    std::string indexSet;
                    for(auto vec : vecData)
                    {
                        std::map<std::string, std::vector<std::string>> addr_coefficient_Map;

                        std::vector<std::string> vecParamInfo;

                        vecParamInfo.push_back(vec["key_value"]);
                        vecParamInfo.push_back(vec["desc_cn"]);
                        vecParamInfo.push_back(vec["coefficient"]);

                        // 地址：KeyValue，Desc, Coefficient
                        addr_coefficient_Map[vec["addr"]] = vecParamInfo;

                        // cout << vec["statement_id"] << endl;
                        statementIdMap[vec["statement_id"]] = addr_coefficient_Map;

                        // 别名
                        indexSet += vec["key_value"] + ",";
                    }

                    // 创建 JSON 对象
                    Json::Value root;
                    // 设置顶层字段
                    root["ChanCode"] = std::to_string(chanCode);
                    root["ChanDesc"] = Json::nullValue; // null 值
                    root["ChanType"] = "7";
                    root["DataProtocol"] = "5";
                    root["WayUid"] = "1575875275";

                    // 创建 Custom 对象
                    Json::Value custom;
                    custom["BeginCh"] = "$";
                    custom["DevName"] = vec; // 设备名称就是Topic主题名
                    custom["EndCh"] = "\\r\\n";

                    // 创建 DataCh 数组
                    Json::Value dataCh(Json::arrayValue);
                    Json::Value splitCh1;
                    splitCh1["SplitCh"] = ",";
                    dataCh.append(splitCh1);

                    // Json::Value splitCh2;
                    // splitCh2["SplitCh"] = "=";
                    // dataCh.append(splitCh2);

                    custom["DataCh"] = dataCh;

                    // 创建 Results 数组
                    Json::Value results(Json::arrayValue);

                    Json::Value tmpResult;
                    // 遍历 std::map<std::string, std::map<std::string, std::string>> 生成JSON规则
                    for (const auto& outerPair : statementIdMap)
                    {
                        const std::string& outerKey = outerPair.first; // 语句标识符
                        tmpResult["SentenceName"] = outerKey;

                        const std::map<std::string, std::vector<std::string>>& innerMap = outerPair.second; // 地址

                        for (const auto& innerPair : innerMap)
                        {
                            tmpResult["Addr"] = innerPair.first;
                            tmpResult["DataType"] = "float";

                            tmpResult["Alias"] = innerPair.second.at(0);
                            tmpResult["DataDesc"] = innerPair.second.at(1);

                            std::string coffit = "0,";
                            coffit += innerPair.second.at(2);
                            coffit += ",0";
                            tmpResult["Coefficient"] = coffit;

                            results.append(tmpResult);
                        }
                    }
                    custom["Results"] = results;
                    root["Custom"] = custom;

                    // 将 JSON 对象转换为字符串
                    Json::StreamWriterBuilder writer;
                    string jsonString = Json::writeString(writer, root);

                    // Update语句

                    char update_sql[1024];
                    sprintf(update_sql, "UPDATE channelsdataprotocol SET JsonString=\'%s\' WHERE WayUid='%s' AND ChanCode=%d",
                            jsonString.c_str(), "1575875275", chanCode);

                    MySqlApi *p0 = CMySqlConnectPool::Instance()->GetConnection();
                    if (p0 != NULL)
                    {
                        // 1、更新 iscu.channelsdataprotocol 的JsonString字段
                        p0->ExecuteSql(update_sql);
                        CMySqlConnectPool::Instance()->ReleaseConnection(p0);
                    }

                    keyValue = indexSet;
                }

                MySqlApi *p1 = CMySqlConnectPool::Instance()->GetConnection();
                if (p1 != NULL)
                {
                    // 2、填充 iscu.topicinfo表
                    char insert_sql[256];
                    sprintf(insert_sql, "INSERT INTO topicinfo(TopicName, IndexSet) VALUES('%s', '%s')",
                            vec.c_str(), keyValue.c_str());

                    p1->ExecuteSql(insert_sql);
                    CMySqlConnectPool::Instance()->ReleaseConnection(p1);
                }

                chanCode++;
            }


        }
    }

    int chanCode_chs = 1;
    int chanCode_dataProtocol = 1;

    // 查询Modbus RTU数据
    {
        std::vector<std::string> vecTopicName;
        // channelsdataprotocol表
        {
            char sql[128] = "SELECT * FROM channelsdataprotocol WHERE way_uid=\'30000000\' AND chan_type=310";

            std::vector<std::map<std::string, std::string>> vecData;
            if(configDB->SelectSql(sql, vecData))
            {
                for(auto vec : vecData)
                {
                    // cout << vec["topic_name"] << endl;
                    vecTopicName.push_back(vec["topic_name"]);

                    // iscu数据库插入数据：iscu.channelsdataprotocol表
                    MySqlApi *p1 = CMySqlConnectPool::Instance()->GetConnection();
                    if (p1 != NULL)
                    {
                        char insert_sql[256];
                        sprintf(insert_sql, "INSERT INTO channelsdataprotocol(TopicName, WayUid, ChanType, ChanCode, SlaveId, DataProtocol) VALUES(\'%s\', \'%s\', %d, %d, %d, %d)",
                                vec["topic_name"].c_str(), "1575876387", 7, chanCode_chs, std::stoi(vec["slave_id"]), 2);
                        printf("[%s:%d] %s\n", __FILE__, __LINE__, insert_sql);

                        if(!p1->ExecuteSql(insert_sql))
                        {
                            printf("[%s:%d] %s\n", __FILE__, __LINE__, "MySQL INSERT failed...");
                        }
                    }
                    CMySqlConnectPool::Instance()->ReleaseConnection(p1);
                    chanCode_chs++;
                }
            }
        }

        // sys_config.hldkeymap表
        {
            for(auto vec : vecTopicName)
            {
                std::string keyValue;

                char select_sql[128];
                sprintf(select_sql, "SELECT * FROM hldkeymap WHERE topic_name=\'%s\'", vec.c_str());
                printf("[%s:%d] %s\n", __FILE__, __LINE__, select_sql);

                std::vector<std::map<std::string, std::string>> vecData;
                if(configDB->SelectSql(select_sql, vecData))
                {
                    // 寄存器地址{KeyValue:{ DataType, Coefficient }}
                    std::map<std::string, std::map<std::string, std::vector<std::string>>> funcCode_01Map;
                    std::map<std::string, std::map<std::string, std::vector<std::string>>> funcCode_02Map;
                    std::map<std::string, std::map<std::string, std::vector<std::string>>> funcCode_03Map;
                    std::map<std::string, std::map<std::string, std::vector<std::string>>> funcCode_04Map;

                    // 寄存器:数据类型
                    // std::map<std::string, std::string> regisAddr_DataType_01;
                    // std::map<std::string, std::string> regisAddr_DataType_02;
                    // std::map<std::string, std::string> regisAddr_DataType_03;
                    // std::map<std::string, std::string> regisAddr_DataType_04;

                    std::vector<std::array<float, 2>> regisAddr_DataType_01;
                    std::vector<std::array<float, 2>> regisAddr_DataType_02;
                    std::vector<std::array<float, 2>> regisAddr_DataType_03;
                    std::vector<std::array<float, 2>> regisAddr_DataType_04;

                    std::string indexSet;
                    for(auto vec : vecData)
                    {
                        std::map<std::string, std::vector<std::string>> aliasDataTypeCoef;
                        std::vector<std::string> vecProperty;
                        vecProperty.push_back(vec["data_type"]);
                        vecProperty.push_back(vec["coefficient"]);

                        aliasDataTypeCoef[vec["key_value"]] = vecProperty;

                        std::array<float, 2> addr_dataType;
                        addr_dataType[0] = std::stof(vec["addr"]);
                        addr_dataType[1] = std::stof(vec["data_type"]);

                        if(std::stof(vec["addr"]) >=0 && std::stof(vec["addr"]) <= 9999)  // 功能码：01
                        {
                            regisAddr_DataType_01.push_back(addr_dataType);

                            funcCode_01Map[vec["addr"]] = aliasDataTypeCoef;
                        }
                        else if(std::stof(vec["addr"]) >=10001 && std::stof(vec["addr"]) <= 19999) // 02
                        {
                            regisAddr_DataType_02.push_back(addr_dataType);

                            funcCode_02Map[vec["addr"]] = aliasDataTypeCoef;
                        }
                        else if(std::stof(vec["addr"]) >=40001 && std::stof(vec["addr"]) <= 49999) // 03
                        {
                            regisAddr_DataType_03.push_back(addr_dataType);

                            funcCode_03Map[vec["addr"]] = aliasDataTypeCoef;
                        }
                        else if(std::stof(vec["addr"]) >=30001 && std::stof(vec["addr"]) <= 39999) // 03
                        {
                            regisAddr_DataType_04.push_back(addr_dataType);

                            funcCode_04Map[vec["addr"]] = aliasDataTypeCoef;
                        }
                        else
                        {
                            printf("[%s:%d] %s\n", __FILE__, __LINE__, "Modbus Data Addr error");
                        }
                    }

                    // -------------------0x01----------------------
                    std::map<int, std::vector<float>> sliceAddr_Map_01;

                    std::vector<float> vecAddr_01;
                    int mapIndex_01 = 1;
                    // 判断功能码01的地址是否连续
                    for(int i = 0; i < regisAddr_DataType_01.size(); i++)
                    {
                        if((i + 1) >= regisAddr_DataType_01.size())
                        {
                            break;
                        }

                        if((regisAddr_DataType_01.at(i).at(0) + 1) == (regisAddr_DataType_01.at(i + 1).at(0)))
                        {
                            if((i + 1) == regisAddr_DataType_01.size())
                            {
                                vecAddr_01.push_back(regisAddr_DataType_01.at(i + 1).at(0));
                            }
                        }
                        else // 地址不连续
                        {
                            if((i + 1) == regisAddr_DataType_01.size())
                            {
                                std::vector<float> tmpAddr;
                                tmpAddr.push_back(regisAddr_DataType_01.at(i + 1).at(0));

                                mapIndex_01++;
                                sliceAddr_Map_01[mapIndex_01] = tmpAddr;
                            }
                            else
                            {
                                std::vector<float> tmpAddr = vecAddr_01;
                                sliceAddr_Map_01[mapIndex_01] = tmpAddr;
                                vecAddr_01.clear();
                                mapIndex_01++;
                            }
                        }

                        vecAddr_01.push_back(regisAddr_DataType_01.at(i).at(0));
                    }

                    // -------------------0x02----------------------
                    std::map<int, std::vector<float>> sliceAddr_Map_02;
                    std::vector<float> vecAddr_02;
                    int mapIndex_02 = 1;
                    // 判断功能码02的地址是否连续
                    for(int i = 0; i < regisAddr_DataType_02.size(); i++)
                    {
                        if((i + 1) >= regisAddr_DataType_02.size())
                        {
                            break;
                        }

                        if((regisAddr_DataType_02.at(i).at(0) + 1) == (regisAddr_DataType_02.at(i + 1).at(0)))
                        {
                            if((i + 1) == regisAddr_DataType_02.size())
                            {
                                vecAddr_01.push_back(regisAddr_DataType_02.at(i + 1).at(0));
                            }
                        }
                        else // 地址不连续
                        {
                            if((i + 1) == regisAddr_DataType_02.size())
                            {
                                std::vector<float> tmpAddr;
                                tmpAddr.push_back(regisAddr_DataType_02.at(i + 1).at(0));

                                mapIndex_02++;
                                sliceAddr_Map_02[mapIndex_02] = tmpAddr;
                            }
                            else
                            {
                                std::vector<float> tmpAddr = vecAddr_02;
                                sliceAddr_Map_02[mapIndex_02] = tmpAddr;
                                vecAddr_02.clear();
                                mapIndex_02++;
                            }
                        }

                        vecAddr_02.push_back(regisAddr_DataType_02.at(i).at(0));
                    }

                    // -------------------0x03----------------------
                    std::map<int, std::vector<float>> sliceAddr_Map_03;
                    std::vector<float> vecAddr_03;
                    int mapIndex_03 = 1;

                    for(int i = 0; i < regisAddr_DataType_03.size(); i++)
                    {
                        if((i + 1) >= regisAddr_DataType_03.size())
                        {
                            break;
                        }

                        int calcAddr = int(regisAddr_DataType_03.at(i).at(0));
                        int calaAddrDataTypeLen = dataType2ModbusRegisterNum(regisAddr_DataType_03.at(i).at(1));
                        int calcAddrNext = int(regisAddr_DataType_03.at(i + 1).at(0));
                        // int calcAddrNextDataTypeLen = dataType2ModbusRegisterNum(regisAddr_DataType_03.at(i + 1).at(1));

                        if((calcAddr + calaAddrDataTypeLen) >= calcAddrNext) // 连续
                        {
                            if((i + 1) == regisAddr_DataType_03.size())
                            {
                                vecAddr_03.push_back(regisAddr_DataType_03.at(i + 1).at(0));
                            }
                        }
                        else
                        {
                            if((i + 1) == regisAddr_DataType_03.size())
                            {
                                std::vector<float> tmpAddr;
                                tmpAddr.push_back(regisAddr_DataType_03.at(i + 1).at(0));

                                mapIndex_03++;
                                sliceAddr_Map_03[mapIndex_02] = tmpAddr;
                            }
                            else
                            {
                                std::vector<float> tmpAddr = vecAddr_03;
                                sliceAddr_Map_03[mapIndex_03] = tmpAddr;
                                vecAddr_03.clear();
                                mapIndex_03++;
                            }
                        }

                        vecAddr_03.push_back(regisAddr_DataType_03.at(i).at(0));
                    }

                    // -------------------0x04----------------------
                    std::map<int, std::vector<float>> sliceAddr_Map_04;
                    std::vector<float> vecAddr_04;
                    int mapIndex_04 = 1;

                    for(int i = 0; i < regisAddr_DataType_04.size(); i++)
                    {
                        if((i + 1) >= regisAddr_DataType_04.size())
                        {
                            break;
                        }

                        int calcAddr = int(regisAddr_DataType_03.at(i).at(0));
                        int calaAddrDataTypeLen = dataType2ModbusRegisterNum(regisAddr_DataType_03.at(i).at(1));
                        int calcAddrNext = int(regisAddr_DataType_03.at(i + 1).at(0));
                        // int calcAddrNextDataTypeLen = dataType2ModbusRegisterNum(regisAddr_DataType_03.at(i + 1).at(1));

                        if((calcAddr + calaAddrDataTypeLen) >= calcAddrNext) // 连续
                        {
                            if((i + 1) == regisAddr_DataType_04.size())
                            {
                                vecAddr_03.push_back(regisAddr_DataType_04.at(i + 1).at(0));
                            }
                        }
                        else
                        {
                            if((i + 1) == regisAddr_DataType_03.size())
                            {
                                std::vector<float> tmpAddr;
                                tmpAddr.push_back(regisAddr_DataType_03.at(i + 1).at(0));

                                mapIndex_04++;
                                sliceAddr_Map_03[mapIndex_02] = tmpAddr;
                            }
                            else
                            {
                                std::vector<float> tmpAddr = vecAddr_03;
                                sliceAddr_Map_03[mapIndex_03] = tmpAddr;
                                vecAddr_03.clear();
                                mapIndex_04++;
                            }
                        }

                        vecAddr_04.push_back(regisAddr_DataType_03.at(i).at(0));
                    }


                    // 生成 Modbus配置的JSON规则
                }



            }
        }

    }

    // 查询Modbus TCP数据
    {
        std::vector<std::string> vecTopicName;
        // channelsdataprotocol表
        {
            char sql[128] = "SELECT * FROM channelsdataprotocol WHERE way_uid=\'30000000\' AND chan_type=320";

            std::vector<std::map<std::string, std::string>> vecData;
            if(configDB->SelectSql(sql, vecData))
            {
                for(auto vec : vecData)
                {
                    // cout << vec["topic_name"] << endl;
                    vecTopicName.push_back(vec["topic_name"]);

                    // ISCU数据库插入数据：iscu.channelsdataprotocol表
                    MySqlApi *p1 = CMySqlConnectPool::Instance()->GetConnection();
                    if (p1 != NULL)
                    {
                        char insert_sql[256];
                        sprintf(insert_sql, "INSERT INTO channelsdataprotocol(TopicName, WayUid, ChanType, ChanCode, SlaveId, DataProtocol) VALUES(\'%s\', \'%s\', %d, %d, %d, %d)",
                                vec["topic_name"].c_str(), "1575876387", 7, chanCode_chs, std::stoi(vec["slave_id"]), 6);
                        printf("[%s:%d] %s\n", __FILE__, __LINE__, insert_sql);

                        if(!p1->ExecuteSql(insert_sql))
                        {
                            printf("[%s:%d] %s\n", __FILE__, __LINE__, "MySQL INSERT failed...");
                        }
                    }
                    CMySqlConnectPool::Instance()->ReleaseConnection(p1);
                    chanCode_chs++;
                }
            }
        }
    }

    // 查询OPC UA数据
    {
        char sql[128] = "SELECT * FROM channelsdataprotocol WHERE way_uid=\'40000000\' AND chan_type=400";
    }

    // 查询Custom数据
    {
        char sql[128] = "SELECT * FROM channelsdataprotocol WHERE way_uid=\'50000000\' AND chan_type=500";
    }



#if 0
    CMySqlConnectPool::Instance()->InitConnection(10);
    MySqlApi *p1 = CMySqlConnectPool::Instance()->GetConnection();
    if (p1 != NULL)
    {
        char sql[128];
        sprintf(sql, "SELECT `client_num`,`utc_time`,`file` FROM file_t%d LIMIT 500;", 1);
        // sprintf(sql, "SELECT * FROM file_t%d LIMIT 500;", 1);

        std::vector<std::map<std::string, std::string>> vecData;
        if (p1->SelectSql(sql, vecData))
        {
            for (auto vec : vecData)
            {
                cout << vec["client_num"] << endl;

                // int clientNum = std::stoi(vec["client_num"]);
                // unsigned long fileTime = std::stoul(vec["utc_time"]);
                // std::string pngBuffer = vec["file"];
                // cout << clientNum << endl;
            }
        }
        else
        {
            printf("SELECT * FROM file execute failed!");
        }

        CMySqlConnectPool::Instance()->ReleaseConnection(p1);
    }
    else
    {
        printf("GetConnection failed!");
    }
#endif

    getchar();

    return 0;
}
